package com.bawei.es.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.bawei.common.core.domain.R;
import com.bawei.common.core.utils.StringUtils;
import com.bawei.es.service.EsDocService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bawei.common.core.domain.R;
import com.bawei.common.core.utils.PageResult;
import com.bawei.common.core.utils.StringUtils;
import com.bawei.es.service.EsDocService;
import com.bawei.mall.product.domain.dto.EsDocFindDTO;
import com.bawei.mall.product.domain.vo.EsDocFindVO;
import com.bawei.system.domain.vo.EsDocInsertVo;
import com.bawei.system.domain.vo.EsDocQueryVo;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class EsDocServiceImpl implements EsDocService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public R<Boolean> batchInsertDocs(List<EsDocInsertVo> esDocInsertVo) {
        BulkRequest request = new BulkRequest();
        esDocInsertVo.forEach(e -> {
            IndexRequest source = new IndexRequest(e.getIndexName()).source(e.getData(), XContentType.JSON);
            if (StringUtils.isNotEmpty(e.getId())) {
                source.id(e.getId());
            }
            request.add(source);
        });
        try {
            BulkResponse bulk = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
            return R.ok(true, "插入成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.fail(false, "插入失败");
    }

    @Override
    public void batch(List<EsDocInsertVo> esDocInsertVos) {
        BulkRequest bulkRequest = new BulkRequest();
        try {
            esDocInsertVos.forEach(esDocInsertVo -> {
                bulkRequest.add(new IndexRequest(esDocInsertVo.getIndexName())
                        .id(esDocInsertVo.id+"")
                        .source(esDocInsertVo.getData(),XContentType.JSON)
                );
            });
            restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
        }catch (Exception e){

        }
    }

    @Override
    public void del(String indexName,Long id) {
        DeleteRequest delete = new DeleteRequest(indexName)
                .id(String.valueOf(id));
        try {
            restHighLevelClient.delete(delete,RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("删除失败");
        }
    }

    @Override
    public R querySuggestions(String indexName, String keyWord, String suggestFiled) {
        SearchRequest request = new SearchRequest(indexName);
        request.source().suggest(new SuggestBuilder().addSuggestion(
                "title_suggest",
                SuggestBuilders.completionSuggestion(suggestFiled)
                        .prefix(keyWord)
                        .skipDuplicates(true)
                        .size(10)
        ));
        SearchResponse response=null;
        try {
            response=restHighLevelClient.search(request,RequestOptions.DEFAULT);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        Suggest suggest = response.getSuggest();
        ArrayList<String> list = new ArrayList<>();
        suggest.getSuggestion("title_suggest").forEach(suggestion -> {
            suggestion.getOptions().forEach(entry ->{
                list.add(entry.getText().string());
            });
        });
        return R.ok(list);
    }

    /**
     * 自动补全
     * @param esDocInsertVo
     * @return
     */
    @Override
    public R queryDocs(EsDocQueryVo esDocInsertVo) {
        SearchRequest request = new SearchRequest(esDocInsertVo.getIndexName());
        //构建查询参数
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.matchAllQuery());
        //构建分页参数
        builder.from((esDocInsertVo.getPageVo().getCurrentPage() - 1) * esDocInsertVo.getPageVo().getPageSize());
        builder.size(esDocInsertVo.getPageVo().getPageSize());
        //构建排序参数
        try {
            SearchResponse search = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            log.info("查询结果：{}", JSONObject.toJSONString(search));
            SearchHit[] hits = search.getHits().getHits();
            List<Map<String,Object>> resultData = new ArrayList<>(hits.length);
            Arrays.stream(hits).forEach(h->{
                Map<String, Object> sourceAsMap = h.getSourceAsMap();
                resultData.add(sourceAsMap);
            });
        } catch (IOException e) {
            log.error("根据条件查询es数据失败：{}", e);
        }
        return null;
    }


    @Override
    public R<PageResult<EsDocFindDTO>> findEsDocs(EsDocFindVO esDocFindVO) {
        long total=0;
        ArrayList<EsDocFindDTO> list = new ArrayList<>();
        try {
            SearchRequest searchRequest = new SearchRequest(esDocFindVO.getIndexName());
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            if (esDocFindVO.getName()!=null){
                boolQueryBuilder.must(QueryBuilders.matchQuery("name",esDocFindVO.getName()));
            }
            if (esDocFindVO.getKeyworks()!=null){
                boolQueryBuilder.must(QueryBuilders.matchQuery("keyworks",esDocFindVO.getKeyworks()));
            }
            searchSourceBuilder.query(boolQueryBuilder);
            searchSourceBuilder.from((esDocFindVO.getPageNum()-1)*esDocFindVO.getPageSize());
            searchSourceBuilder.size(esDocFindVO.getPageSize());
            searchSourceBuilder.highlighter(
                    new HighlightBuilder().field("name").preTags("<span style=\"color: red\">").postTags("</span>")
            );
            searchSourceBuilder.highlighter(
                    new HighlightBuilder().field("keyworks").preTags("<span style=\"color: red\">").postTags("</span>")
            );
            SearchRequest source = searchRequest.source(searchSourceBuilder);
            SearchResponse search = restHighLevelClient.search(source, RequestOptions.DEFAULT);
            total = search.getHits().getTotalHits().value;
            SearchHits hits = search.getHits();
            SearchHit[] hitsHits = hits.getHits();
            for (SearchHit hitsHit : hitsHits) {
                String sourceAsString = hitsHit.getSourceAsString();
                EsDocFindDTO esDocFindDTO = JSON.parseObject(sourceAsString, EsDocFindDTO.class);
                Map<String, HighlightField> map = hitsHit.getHighlightFields();
                HighlightField name = map.get("name");
                HighlightField keyworks = map.get("keyworks");
                if (name!=null){
                    Text[] fragments = name.fragments();
                    String str="";
                    for (Text fragment : fragments) {
                        str+=fragment;
                    }
                    esDocFindDTO.setName(str);
                }
                if (keyworks!=null){
                    Text[] fragments = keyworks.fragments();
                    String str="";
                    for (Text fragment : fragments) {
                        str+=fragment;
                    }
                    esDocFindDTO.setKeyworks(str);
                }
                list.add(esDocFindDTO);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return PageResult.toResult(total,list);
    }



}
